﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SCMS.Model;
using System.Collections;
using System.Transactions;
using SCMS.CoreBusinessLogic.NotificationsManager;

namespace SCMS.CoreBusinessLogic.WRF
{
    public class WareHouseReleaseService : IWareHouseReleaseService
    {
        private INotificationService NotificationServicee;

        public WareHouseReleaseService(INotificationService NotificationServicee)
        {
            this.NotificationServicee = NotificationServicee;
        }

        public bool SaveWRF(Model.WarehouseRelease WR, Model.WarehouseReleaseItem entity)
        {
            using (var dbContext = new SCMSEntities())
            {
                using (TransactionScope scope = new TransactionScope())
                {
                    try
                    {
                        if (WR != null)
                        {
                            dbContext.WarehouseReleases.AddObject(WR);
                            //if (dbContext.SaveChanges() > 0)
                            //{
                            return AddItems(WR, entity, dbContext, scope, true);
                            //}
                            //else { scope.Dispose(); return false; }
                        }
                        else
                        {
                            if (entity.Id.Equals(Guid.Empty))
                                return AddItems(WR, entity, dbContext, scope);
                            else
                            {
                                dbContext.ObjectStateManager.ChangeObjectState(entity, System.Data.EntityState.Modified);
                                if ((dbContext.SaveChanges() > 0)) { scope.Complete(); return true; } else { scope.Dispose(); return false; }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        scope.Dispose();
                        throw new Exception(ex.Message);
                    }
                }
            }
        }

        private bool AddItems(Model.WarehouseRelease wrEntity, Model.WarehouseReleaseItem entity, SCMSEntities dbContext, TransactionScope scope, bool sendmail = false)
        {
            string itemCategory = dbContext.Inventories.FirstOrDefault(p => p.Id == entity.InventoryId).Item.ItemCategory.CategoryCode;
            if (wrEntity == null)
                wrEntity = dbContext.WarehouseReleases.FirstOrDefault(w => w.Id == entity.WarehouseReleaseId);
            entity.Id = Guid.NewGuid();
            if (itemCategory.Equals("C"))
            { entity.AssetId = Guid.Empty; dbContext.WarehouseReleaseItems.AddObject(entity); }
            else
            {
                entity.Quantity = 1;
                Model.Asset ass = dbContext.Assets.FirstOrDefault(p => p.Id == entity.AssetId);
                ass.IsReleased = true;
                ass.CurrentOwnerId = wrEntity.ReceivedBy;
                dbContext.ObjectStateManager.ChangeObjectState(ass, System.Data.EntityState.Modified);
                dbContext.WarehouseReleaseItems.AddObject(entity);
            }
            Model.Inventory inv = dbContext.Inventories.First(p => p.Id == entity.InventoryId);
            inv.Quantity -= (Int64)entity.Quantity;
            dbContext.ObjectStateManager.ChangeObjectState(inv, System.Data.EntityState.Modified);

            if ((dbContext.SaveChanges() > 0))
            {
                if (sendmail)
                    NotificationServicee.SendNotification(NotificationServicee.GetApproverEmailAddress(1, NotificationHelper.wrnCode), NotificationHelper.wrnMsgBody, NotificationHelper.wrnsubject);
                scope.Complete();
                return true;
            }
            else { scope.Dispose(); return false; }
        }

        public bool IsWRNItemDeleted(Guid wrnItemId)
        {
            using (var db = new SCMSEntities())
            {
                Model.WarehouseReleaseItem wrnitm = db.WarehouseReleaseItems.FirstOrDefault(p => p.Id == wrnItemId);
                string itemCategory = db.Inventories.FirstOrDefault(p => p.Id == wrnitm.InventoryId).Item.ItemCategory.CategoryCode;
                if (itemCategory.Equals("A"))
                {
                    wrnitm.Quantity = 1;
                    Model.Asset ass = db.Assets.FirstOrDefault(p => p.Id == wrnitm.AssetId);
                    ass.IsReleased = false;
                    ass.CurrentOwnerId = null;
                    db.ObjectStateManager.ChangeObjectState(ass, System.Data.EntityState.Modified);
                }
                Model.Inventory inv = db.Inventories.First(p => p.Id == wrnitm.InventoryId);
                inv.Quantity += (Int64)wrnitm.Quantity;
                db.ObjectStateManager.ChangeObjectState(inv, System.Data.EntityState.Modified);
                db.WarehouseReleaseItems.DeleteObject(wrnitm);
                return db.SaveChanges() > 0 ? true : false;
            }
        }

        public void RejectWRO(Guid wroId)
        {
            using (var context = new SCMSEntities())
            {
                using (TransactionScope scope = new TransactionScope())
                {
                    try
                    {
                        var wrnItems = context.WarehouseReleaseItems.Where(w => w.WarehouseReleaseId == wroId).ToList();
                        foreach (var wrnItem in wrnItems)
                        {
                            string itemCategory = context.Inventories.FirstOrDefault(p => p.Id == wrnItem.InventoryId).Item.ItemCategory.CategoryCode;
                            if (itemCategory.Equals("A"))
                            {
                                wrnItem.Quantity = 1;
                                Model.Asset ass = context.Assets.FirstOrDefault(p => p.Id == wrnItem.AssetId);
                                ass.IsReleased = false;
                                ass.CurrentOwnerId = null;
                                context.ObjectStateManager.ChangeObjectState(ass, System.Data.EntityState.Modified);
                            }
                            Model.Inventory inv = context.Inventories.First(p => p.Id == wrnItem.InventoryId);
                            inv.Quantity += (Int64)wrnItem.Quantity;
                            context.ObjectStateManager.ChangeObjectState(inv, System.Data.EntityState.Modified);
                            context.SaveChanges();
                        }
                        scope.Complete();
                    }
                    catch (Exception ex)
                    {
                        scope.Dispose();
                        throw ex;
                    }
                }
            }
        }

        public string GenerateUniquNumber(CountryProgramme cp)
        {
            string code = "WRO/DRC/" + cp.Country.ShortName + "/";
            string refNumber = "";
            long count = 1;
            using (var dbContext = new SCMSEntities())
            {
                var total = dbContext.WarehouseReleases.Where(p => p.CountryProgrammeId == cp.Id && p.IsSubmitted == true).Count();
                count = total;
                Model.WarehouseRelease m = null;
                do
                {
                    count++;
                    if (count < 10000)
                    {
                        if (count < 10)
                            refNumber = code + "0000" + count;
                        if (count < 100 & count >= 10)
                            refNumber = code + "000" + count;
                        if (count < 1000 & count >= 100)
                            refNumber = code + "00" + count;
                        if (count < 10000 & count >= 1000)
                            refNumber = code + "0" + count;
                    }
                    m = dbContext.WarehouseReleases.FirstOrDefault(p => p.RefNumber == refNumber);
                } while (m != null);
                return refNumber;
            }
        }

        public List<object> GetInventoryItems(Guid cpid, Guid warehouseId)
        {
            using (var db = new SCMSEntities())
            {
                List<object> mm = (from n in db.Inventories
                                   join i in db.Items on n.ItemId equals i.Id
                                   where n.CountryProgrammeId == cpid && n.WareHouseId == warehouseId && i.CountryProgrammeId == cpid
                                   select new
                                   {
                                       n.Id,
                                       i.Name
                                   }).ToList<object>();

                return mm;
            }
        }

        public List<Model.Asset> GetAssets(Guid InventoryId)
        {
            using (var db = new SCMSEntities())
            {
                Model.Inventory invt = db.Inventories.FirstOrDefault(p => p.Id == InventoryId);
                return db.Assets.Where(p => p.ItemId == invt.ItemId && p.CurrentWareHouseId == invt.WareHouseId && p.IsReleased == false).ToList<Asset>();
            }
        }

        public List<WarehouseReleaseItem> GetWRNItems(Guid WRNId)
        {

            using (var db = new SCMSEntities())
            {
                List<WarehouseReleaseItem> mm = db.WarehouseReleaseItems.Where(p => p.WarehouseReleaseId == WRNId).ToList();
                foreach (WarehouseReleaseItem item in mm)
                {
                    Model.Inventory a = item.Inventory;
                    Model.Item i = a.Item;
                    Model.ItemCategory ic = i.ItemCategory;
                    Model.Asset ast = item.Asset;
                    Model.UnitOfMeasure u = a.Item.UnitOfMeasure;
                }
                return mm;
            }
        }

        public List<WarehouseRelease> GetWRNs(Guid CPId)
        {
            using (var db = new SCMSEntities())
            {
                DeleteWRNWithNoItems();
                List<WarehouseRelease> wrn = db.WarehouseReleases.Where(p => p.CountryProgrammeId == CPId).OrderByDescending(w => w.PreparedOn).ToList();
                foreach (WarehouseRelease item in wrn)
                {
                    foreach (var writemz in item.WarehouseReleaseItems.ToList())
                    {
                        Model.Inventory a = writemz.Inventory;
                        Model.Item i = a.Item;
                        Model.Asset ast = writemz.Asset;
                        Model.UnitOfMeasure u = a.Item.UnitOfMeasure;
                    }
                }
                return wrn;
            }
        }

        public List<WarehouseRelease> GetWRNs4WB(Guid CPId)
        {
            using (var db = new SCMSEntities())
            {
                DeleteWRNWithNoItems();
                List<WarehouseRelease> wrn = db.WarehouseReleases.Where(w => w.CountryProgrammeId == CPId && w.IsApproved == true).OrderByDescending(w => w.PreparedOn).ToList();
                foreach (WarehouseRelease item in wrn)
                {
                    foreach (var writemz in item.WarehouseReleaseItems.ToList())
                    {
                        Model.Inventory a = writemz.Inventory;
                        Model.Item i = a.Item;
                        Model.Asset ast = writemz.Asset;
                        Model.UnitOfMeasure u = a.Item.UnitOfMeasure;
                    }
                }
                return wrn;
            }
        }

        private void DeleteWRNWithNoItems()
        {
            using (var db = new SCMSEntities())
            {
                var wrns = from c in db.WarehouseReleases where !(from o in db.WarehouseReleaseItems select o.WarehouseReleaseId).Contains(c.Id) select c;
                foreach (WarehouseRelease item in wrns) db.WarehouseReleases.DeleteObject(item);
                db.SaveChanges();
            }
        }

        public string GetStaffName(Guid StaffId)
        {
            using (var db = new SCMSEntities())
            {
                return db.VStaffDetails.First(p => p.StaffID == StaffId).StaffName;
            }
        }

        public List<WarehouseRelease> GetWRNsForApproval(Staff currentStaff)
        {
            try
            {
                using (var context = new SCMSEntities())
                {
                    return context.WarehouseReleases.Where(w => w.IsSubmitted == true && w.IsApproved == false && w.IsRejected == false && w.ApprovedBy == currentStaff.Id
                        && w.CountryProgrammeId == currentStaff.CountrySubOffice.CountryProgrammeId).ToList();

                }
            }
            catch (Exception ex)
            {
                return new List<Model.WarehouseRelease>();
            }
        }

        public WarehouseRelease GetWROById(Guid Id)
        {
            using (var context = new SCMSEntities())
            {
                var wro = context.WarehouseReleases.FirstOrDefault(w => w.Id == Id);
                var person = wro.Staff1.Person;
                return wro;
            }
        }

        public bool SaveApproved(WarehouseRelease wro)
        {
            using (var context = new SCMSEntities())
            {
                context.WarehouseReleases.Attach(wro);
                context.ObjectStateManager.ChangeObjectState(wro, System.Data.EntityState.Modified);
                return context.SaveChanges() > 0;
            }
        }

        public bool DeleteWarehouseReleaseById(Guid wroId)
        {
            using (var context = new SCMSEntities())
            {
                var wro = context.WarehouseReleases.FirstOrDefault(w => w.Id == wroId);
                context.WarehouseReleases.DeleteObject(wro);
                return context.SaveChanges() > 0;
            }
        }

        public bool DeleteWarehouseReleaseItemById(Guid wroItemId)
        {
            using (var context = new SCMSEntities())
            {
                var wroItem = context.WarehouseReleaseItems.FirstOrDefault(w => w.Id == wroItemId);
                context.WarehouseReleaseItems.DeleteObject(wroItem);
                return context.SaveChanges() > 0;
            }
        }
    }
}
